﻿// Decompiled with JetBrains decompiler
// Type: Netick.AreaOfInterestLayer
// Assembly: Netick, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 6726ECA1-C773-4CF7-8952-E81B30D93B52
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.xml

using System;
using System.Collections.Generic;
using System.Numerics;
using System.Runtime.CompilerServices;

#nullable disable
namespace Netick;

public sealed class AreaOfInterestLayer
{
  public readonly NetickEngine Engine;
  public readonly InterestManagement IM;
  public readonly InterestManagementGroup[,,] Cells;
  public readonly int GroupCount;
  public readonly int CellsCountPerRowX;
  public readonly int CellsCountPerRowY;
  public readonly int CellsCountPerRowZ;
  public readonly int CellSize;

  internal AreaOfInterestLayer(
    InterestManagement im,
    Vector3 worldSize,
    float cellSize,
    ref int groupCounter)
  {
    this.Engine = im.Engine;
    this.IM = im;
    this.CellSize = (int) Math.Clamp(cellSize, 0.0f, worldSize.Length());
    this.CellsCountPerRowX = NetickUtils.RoundToNearestEven((float) (int) MathF.Ceiling(worldSize.X / (float) this.CellSize));
    this.CellsCountPerRowY = NetickUtils.RoundToNearestEven((float) (int) MathF.Ceiling(worldSize.Y / (float) this.CellSize));
    this.CellsCountPerRowZ = NetickUtils.RoundToNearestEven((float) (int) MathF.Ceiling(worldSize.Z / (float) this.CellSize));
    this.GroupCount = this.CellsCountPerRowX * this.CellsCountPerRowY * this.CellsCountPerRowZ;
    this.Cells = new InterestManagementGroup[this.CellsCountPerRowX, this.CellsCountPerRowY, this.CellsCountPerRowZ];
    for (int x = 0; x < this.CellsCountPerRowX; ++x)
    {
      for (int y = 0; y < this.CellsCountPerRowY; ++y)
      {
        for (int z = 0; z < this.CellsCountPerRowZ; ++z)
          this.Cells[x, y, z] = this.IM.CreateAoIGroup(ref groupCounter, 100, new Vector3(((float) x - (float) this.CellsCountPerRowX / 2f) * cellSize, ((float) y - (float) this.CellsCountPerRowY / 2f) * cellSize, ((float) z - (float) this.CellsCountPerRowZ / 2f) * cellSize), new NetickVector3Int(x, y, z));
      }
    }
  }

  internal static int CalcAoILayerGroupCount(Vector3 worldSize, int cellSize)
  {
    int num1 = (int) Math.Clamp((float) cellSize, 0.0f, worldSize.Length());
    int nearestEven1 = NetickUtils.RoundToNearestEven((float) (int) MathF.Ceiling(worldSize.X / (float) num1));
    int nearestEven2 = NetickUtils.RoundToNearestEven((float) (int) MathF.Ceiling(worldSize.Y / (float) num1));
    int nearestEven3 = NetickUtils.RoundToNearestEven((float) (int) MathF.Ceiling(worldSize.Z / (float) num1));
    int num2 = nearestEven2;
    return nearestEven1 * num2 * nearestEven3;
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  internal void Move(Entity entity, Vector3 newPos)
  {
    if (Vector3.op_Equality(entity.Position, newPos))
      return;
    entity.Position = newPos;
    NetickVector3Int cell = this.ConvertFromWorldToCell(newPos);
    this.IM.ServerSetEntityInterestGroup(entity, this.Cells[cell.X, cell.Y, cell.Z]);
  }

  internal void MoveNoCheck(Entity entity, Vector3 newPos)
  {
    entity.Position = newPos;
    NetickVector3Int cell = this.ConvertFromWorldToCell(newPos);
    this.IM.ServerSetEntityInterestGroup(entity, this.Cells[cell.X, cell.Y, cell.Z]);
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public NetickVector3Int ConvertFromWorldToCell(Vector3 pos)
  {
    return new NetickVector3Int(Math.Clamp(this.CellsCountPerRowX / 2 + (int) MathF.Floor(pos.X / (float) this.CellSize), 0, this.CellsCountPerRowX - 1), Math.Clamp(this.CellsCountPerRowY / 2 + (int) MathF.Floor(pos.Y / (float) this.CellSize), 0, this.CellsCountPerRowY - 1), Math.Clamp(this.CellsCountPerRowZ / 2 + (int) MathF.Floor(pos.Z / (float) this.CellSize), 0, this.CellsCountPerRowZ - 1));
  }

  public InterestManagementGroup GetGroupByPosition(Vector3 position)
  {
    NetickVector3Int cell = this.ConvertFromWorldToCell(position);
    return this.Cells[cell.X, cell.Y, cell.Z];
  }

  internal void CalcBoxInterest(
    int cliIndex,
    List<InterestManagementGroup> imList,
    NetickBounds box)
  {
    float cellSize = (float) this.CellSize;
    int nearestEven1 = NetickUtils.RoundToNearestEven(MathF.Ceiling(box.Size.X / cellSize));
    int nearestEven2 = NetickUtils.RoundToNearestEven(MathF.Ceiling(box.Size.Y / cellSize));
    int nearestEven3 = NetickUtils.RoundToNearestEven(MathF.Ceiling(box.Size.Z / cellSize));
    float num1 = box.Size.X / (float) nearestEven1;
    float num2 = box.Size.Y / (float) nearestEven2;
    float num3 = box.Size.Z / (float) nearestEven3;
    int num4 = nearestEven1 + 1;
    int num5 = nearestEven2 + 1;
    int num6 = nearestEven3 + 1;
    Vector3 vector3 = Vector3.op_Subtraction(box.Center, Vector3.op_Division(box.Size, 2f));
    NetickVector3Int netickVector3Int = new NetickVector3Int();
    for (int index1 = 0; index1 < num4; ++index1)
    {
      float num7 = vector3.X + (float) index1 * num1;
      for (int index2 = 0; index2 < num5; ++index2)
      {
        float num8 = vector3.Y + (float) index2 * num2;
        for (int index3 = 0; index3 < num6; ++index3)
        {
          float num9 = vector3.Z + (float) index3 * num3;
          NetickVector3Int cell1 = this.ConvertFromWorldToCell(new Vector3(num7, num8, num9));
          InterestManagementGroup cell2 = this.Cells[cell1.X, cell1.Y, cell1.Z];
          if (!cell2.Clients[cliIndex])
          {
            cell2.Clients[cliIndex] = true;
            imList.Add(cell2);
          }
        }
      }
    }
  }
}
